package com.tsy.pointcloud.controller;

import com.tsy.common.annotation.Anonymous;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;


@RestController
public class FileRangeController {
    @Value(value = "${tsy.profile}")
    private String basePath;
    @GetMapping("/profile/{converter}/{folder}/{fileName}")
    @Anonymous
    public ResponseEntity<byte[]> getFileRange1(
            @RequestHeader(value = "Range", required = false) String rangeHeader,
            @PathVariable String converter,
            @PathVariable String folder,
            @PathVariable String fileName) {

        String filePath = basePath + File.separator + converter + File.separator + folder + File.separator + fileName;
        return getResponseEntity(rangeHeader, filePath);
    }

    @GetMapping("/profile/{converter}/{handle}/{folder}/{fileName}")
    @Anonymous
    public ResponseEntity<byte[]> getFileRange2(
            @RequestHeader(value = "Range", required = false) String rangeHeader,
            @PathVariable String converter,
            @PathVariable String handle,
            @PathVariable String folder,
            @PathVariable String fileName) {

        String filePath = basePath + File.separator + converter + File.separator + handle + File.separator + folder + File.separator + fileName;
        return getResponseEntity(rangeHeader, filePath);
    }

    private static ResponseEntity<byte[]> getResponseEntity(String rangeHeader, String filePath) {
        File file = new File(filePath);

        if (!file.exists()) {
            return ResponseEntity.notFound().build();
        }

        long fileSize = file.length();

        // 如果没有Range头，返回整个文件
        if (rangeHeader == null) {
            try {
                byte[] data = Files.readAllBytes(file.toPath());
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentLength(data.length);
                // 设置 Content-Disposition 响应头，指定下载文件的名称
                headers.set("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
                return ResponseEntity.ok().headers(headers).body(data);
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
        }

        // 解析Range头
        long start = 0;
        long end = fileSize - 1;
        try {
            String[] parts = rangeHeader.replace("bytes=", "").split("-");
            start = Long.parseLong(parts[0]);
            if (parts.length > 1 && !parts[1].isEmpty()) {
                end = Long.parseLong(parts[1]);
            }
            end = Math.min(end, fileSize - 1);

            // 验证范围有效性
            if (start > end || start >= fileSize) {
                return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE).build();
            }

            // 读取指定范围的字节
            int rangeLength = (int) (end - start + 1);
            byte[] data = new byte[rangeLength];

            try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
                // 从指定位置读取数据
                randomAccessFile.seek(start);
                // 读取指定长度的数据
                randomAccessFile.readFully(data);

                // 设置响应头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentLength(rangeLength);
                headers.set("Content-Range", String.format("bytes %d-%d/%d", start, end, fileSize));
                headers.set("Accept-Ranges", "bytes");

                return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
                        .headers(headers)
                        .body(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}
